classdef XeNMRSystem < NMRGyroscope.NMRSystem.AbstractNMRSystem
    %XENMRSYSTEM Summary of this class goes here
    %   Detailed explanation goes here
    
    properties        
        resonance129
        resonance131
        pid129
        pid131
    end
    
    methods
        function obj = XeNMRSystem(session, controller)
            %XENMRSYSTEM Construct an instance of this class
            %   Detailed explanation goes here
            if nargin == 1
                controller = NMRGyroscope.DeviceController.MainDeviceController(session);
            end
            
            obj@NMRGyroscope.NMRSystem.AbstractNMRSystem(session, controller);
            L = log4m.getLogger();
            L.info('XeNMRSystem', 'XeNMRSystem object created.');                                           
        end
    end
    
    %% Public Methods Defined Separatedly
    methods        
        [fft_data, fidSpectrum]  = GET_ShockFIDSpectrum(obj, varargin);
        fidSignal                = GET_FIDSignal(obj, varargin)
        [fidSpectrum, fft_data]  = GET_FIDSpectrum(obj, fid_signal, varargin)
        [fidSignal, fidSpectrum] = GET_FIDResonance(obj, varargin)
        [pid129, pid131]         = GET_OptimalPIDParameters(obj, varargin)
        bodeData                 = GET_BodePlotData(obj, varargin)
        psdData                  = GET_SensitivityPSDData(obj, varargin)
        
        freqRatio = DO_FIDSequence(obj, varargin)
        [fidSignal, fidSpectrum, shock_freq] = DO_FindNMRResonance(obj)
    end
    %%
    methods
        function dispResonance(obj)
            figure; 
            ax1 = subplot(2, 1, 1);
            plot(obj.resonance129.fit, obj.resonance129.data.frequency, obj.resonance129.data.amplitude);
            grid(ax1, 'on'); xlabel(ax1, 'Freuqency (Hz)'); ylabel(ax1, 'FFT');
            title(ax1, sprintf('f_{129}=%8.4f Hz, gamma=%3.2f mHz, gof=%3.4f, ratio=%8.7f', obj.resonance129.fit.w0, 1000*obj.resonance129.fit.gamma, obj.resonance129.gof.rsquare, obj.getFrequencyRatio));
            ax2 = subplot(2, 1, 2);
            plot(obj.resonance131.fit, obj.resonance131.data.frequency, obj.resonance131.data.amplitude);
            grid(ax2, 'on'); xlabel(ax2, 'Freuqency (Hz)'); ylabel(ax2, 'FFT');
            title(ax2, sprintf('f_{131}=%8.4f Hz, gamma=%3.2f mHz, gof=%3.4f', obj.resonance131.fit.w0, 1000*obj.resonance131.fit.gamma, obj.resonance131.gof.rsquare));
        end
    end
    %% 
    methods
        function obj = lockXe129(obj)
            obj.controller.lockXe129Frequency(obj.pid129);
            obj.controller.syncDevice();
        end
        function obj = unLockXe129(obj)
            obj.controller.unLockXe129Frequency();
            obj.controller.syncDevice();
        end
        function obj = lockXe131(obj)
            obj.controller.lockXe131Frequency(obj.pid131);
            obj.controller.syncDevice();
        end
        function obj = unLockXe131(obj)
            obj.controller.unLockXe131Frequency();
            obj.controller.syncDevice();
        end
        
        function obj = setXe129Frequency(obj, freq)
            if nargin == 1
                freq = obj.getXe129EstFreq();
            end
            obj.controller.setNMRDrivingFrequency129(freq);
        end
        function obj = setXe131Frequency(obj, freq)
            if nargin == 1
                freq = obj.getXe131EstFreq();
            end
            obj.controller.setNMRDrivingFrequency131(freq);
        end
        function obj = enableXe129DrivingAmplitude(obj)
            obj.controller.enableNMRDriving129();
        end
        function obj = enableXe129DrivingAmplitudeOnly(obj)
            obj.controller.enableNMRDriving129();
            obj.controller.disableNMRDriving131();
        end
        function obj = enableXe131DrivingAmplitude(obj)
            obj.controller.enableNMRDriving131();
        end
        function obj = enableXe131DrivingAmplitudeOnly(obj)
            obj.controller.enableNMRDriving131();
            obj.controller.disableNMRDriving129();
        end
        function obj = disableXe129DrivingAmplitude(obj)
            obj.controller.disableNMRDriving129();
        end
        function obj = disableXe131DrivingAmplitude(obj)
            obj.controller.disableNMRDriving131();
        end
        function obj = fireXeDriving(obj)
            obj.controller.enableNMRDriving();
        end
        function obj = silenceXeDriving(obj)
            obj.controller.disableNMRDriving();
        end
        
        function freq = getXe129EstFreq(obj)
            volt = obj.controller.getCurrentControlVoltX();
            freq = volt*obj.controller.Conversions.BxDC.Xe129Ratio;
        end
        function freq = getXe131EstFreq(obj)
            volt = obj.controller.getCurrentControlVoltX();
            freq = volt*obj.controller.Conversions.BxDC.Xe131Ratio;
        end
        
        function ratio = getFrequencyRatio(obj)
            ratio = obj.resonance129.frequency/obj.resonance131.frequency;
        end
        function obj = go2Resonance(obj, pause_time)
            L=log4m.getLogger;
            
            if nargin == 1
                pause_time = 10;
            end
            
            f129Old=obj.controller.getNMRDrivingFrequency129();
            f131Old=obj.controller.getNMRDrivingFrequency131();
            obj.controller.setNMRDrivingFrequency129(obj.resonance129.frequency);
            obj.controller.setNMRDrivingFrequency131(obj.resonance131.frequency);
            pause(pause_time);
            obj.controller.setNMRZeroPhase129();
            obj.controller.setNMRZeroPhase131();
            
            obj.resonance129.phase = obj.controller.getNMRXe129DemodPhase();
            obj.resonance131.phase = obj.controller.getNMRXe131DemodPhase();
            L.info('SimpleNMRG::go2Resonance', ...
                   sprintf('Rosonant points of Xe129 and Xe131 reset: f129 = %5.6f -> %5.6f; f131 = %5.6f -> %5.6f, ', ...
                           f129Old, obj.resonance129.frequency, ...
                           f131Old, obj.resonance131.frequency));
        end
        function obj = go2Resonance129(obj, pause_time)
            L=log4m.getLogger;
            
            if nargin == 1
                pause_time = 10;
            end
            
            f129Old=obj.controller.getNMRDrivingFrequency129();
            obj.controller.setNMRDrivingFrequency129(obj.resonance129.frequency);
            pause(pause_time);
            obj.controller.setNMRZeroPhase129();
            obj.resonance129.phase = obj.controller.getNMRXe129DemodPhase();
            
            L.info('SimpleNMRG::go2Resonance129', ...
                   sprintf('Rosonant point of Xe129 reset: f129 = %5.6f -> %5.6f', ...
                           f129Old, obj.resonance129.frequency));
        end
        function obj = go2Resonance131(obj, pause_time)
            L=log4m.getLogger;
            
            if nargin == 1
                pause_time = 10;
            end
            
            f131Old=obj.controller.getNMRDrivingFrequency131();
            obj.controller.setNMRDrivingFrequency131(obj.resonance131.frequency);
            pause(pause_time);
            obj.controller.setNMRZeroPhase131();
            obj.resonance131.phase = obj.controller.getNMRXe131DemodPhase();
            
            L.info('SimpleNMRG::go2Resonance131', ...
                   sprintf('Rosonant point of Xe131 reset: f131 = %5.6f -> %5.6f', ...
                           f131Old, obj.resonance131.frequency));
        end
        
    end
end

